package com.xiaoma.netty.server;

import com.xiaoma.entity.RpcRequest;
import com.xiaoma.entity.RpcResponse;
import com.xiaoma.provider.ServiceProviderImpl;
import com.xiaoma.registry.ServiceRegistry;
import com.xiaoma.server.RequestHandler;
import com.xiaoma.utils.ThreadPoolFactory;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;

/**
 * @Author: xiaoma
 * @Date: 2021/7/5 15:37
 * @description: Netty服务端侧处理器
 */
public class NettyServerHandler extends SimpleChannelInboundHandler<RpcRequest> {

    private static final Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);

    private static RequestHandler requestHandler;

    private static final String THREAD_NAME_PREFIX = "netty-server-handler";

    private static final ExecutorService threadPool;


    static {
        requestHandler = new RequestHandler();
        threadPool = ThreadPoolFactory.createDefaultThreadPool(THREAD_NAME_PREFIX);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequest msg) throws Exception {
        //使用线程池批量创建线程处理请求
        threadPool.execute(() -> {
            try {
                logger.info("服务器接收到请求: {}", msg);
                //处理RpcRequest 得到返回值
                Object result = requestHandler.handle(msg);
                //将返回值写入缓存并刷新
                ChannelFuture future = ctx.writeAndFlush(RpcResponse.success(result));
                //给ChannelFuture注册监听器，监控我们关心的事件
                future.addListener(ChannelFutureListener.CLOSE);
            } finally {
                ReferenceCountUtil.release(msg);
            }
        });

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("处理过程调用时有错误发生:");
        cause.printStackTrace();
        ctx.close();
    }

}

